1 /**
2 Copyright: Copyright (c) 2021, Joakim Brännström. All rights reserved.
3 License: $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost Software License 1.0)
4 Author: Joakim Brännström (joakim.brannstrom@gmx.com)
5 */
6 module code_checker.cache;
7 
8 import logger = std.experimental.logger;
9 import std.exception : collectException;
10 
11 import my.path;
12 
13 import code_checker.database : TrackFile;
14 
15 struct FileStatCache {
16     import std.datetime : Clock, SysTime;
17     import std.file : timeLastModified;
18     import my.hash : checksum, makeChecksum64, Checksum64;
19 
20     TrackFile[AbsolutePath] cache_;
21     SysTime[AbsolutePath] timeStamp_;
22     Checksum64[AbsolutePath] checkSum_;
23 
24     TrackFile get(AbsolutePath p) @safe nothrow {
25         try {
26             return cache_.require(p, TrackFile(p, getChecksum(p), getTimeStamp(p)));
27         } catch (Exception e) {
28         }
29         return TrackFile.init;
30     }
31 
32     SysTime getTimeStamp(AbsolutePath p) @safe nothrow {
33         try {
34             return timeStamp_.require(p, timeLastModified(p));
35         } catch (Exception e) {
36             logger.trace(e.msg).collectException;
37         }
38         return Clock.currTime;
39     }
40 
41     Checksum64 getChecksum(AbsolutePath p) @trusted nothrow {
42         try {
43             return checkSum_.require(p, checksum!makeChecksum64(p));
44         } catch (Exception e) {
45             logger.trace(e.msg).collectException;
46         }
47         return Checksum64.init;
48     }
49 
50     void drop(AbsolutePath p) @safe nothrow {
51         cache_.remove(p);
52         timeStamp_.remove(p);
53         checkSum_.remove(p);
54     }
55 }
56 
57 TrackFile getTrackFile(Path p) @trusted nothrow {
58     import std.datetime : Clock;
59     import std.file : timeLastModified;
60     import my.hash : checksum, makeChecksum64, Checksum64;
61 
62     auto cs = () {
63         try {
64             return checksum!makeChecksum64(AbsolutePath(p));
65         } catch (Exception e) {
66             logger.trace(e.msg).collectException;
67         }
68         return Checksum64.init;
69     }();
70 
71     auto ts = () {
72         try {
73             return timeLastModified(p);
74         } catch (Exception e) {
75             logger.trace(e.msg).collectException;
76         }
77         return Clock.currTime;
78     }();
79 
80     return TrackFile(p, cs, ts);
81 }
82 
83 bool isSame(const TrackFile tf, const AbsolutePath p, ref FileStatCache fcache) {
84     import std.math : abs;
85 
86     if ((tf.timeStamp - fcache.getTimeStamp(p)).total!"msecs".abs < 20) {
87         debug logger.trace("timestamp unchanged ", p);
88         return true;
89     }
90 
91     if (tf.checksum == fcache.getChecksum(p)) {
92         debug logger.trace("checksum unchanged ", p);
93         return true;
94     }
95 
96     return false;
97 }